package com.wjy.common.authentication.service;

import com.wjy.rbac.entity.RequestMethodB;
import com.wjy.rbac.entity.RequestUrlB;
import com.wjy.rbac.entity.User;
import com.wjy.rbac.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author ybxxszl
 * @desc RBAC权限验证服务
 * @data 2019年4月12日
 */
@Component
public class RBACService {

    @Autowired
    @Qualifier(value = "userServiceImpl")
    private IUserService userService;

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @SuppressWarnings("unchecked")
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        Object object = authentication.getPrincipal();
        if (object instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) object;
            String username = userDetails.getUsername();
            User user = userService.getByAccount(username);
            if (user != null) {
                String method = request.getMethod();
                String url = request.getRequestURI();
                Map<String, Object> result = userService.get(user.getUserId());
                List<Map<String, Object>> roleList = (List<Map<String, Object>>) result.get("roleList");
                for (Map<String, Object> role : roleList) {
                    List<Map<String, Object>> powerList = (List<Map<String, Object>>) role.get("powerList");
                    for (Map<String, Object> power : powerList) {
                        Set<Integer> methodSet = new HashSet<Integer>();
                        Set<String> urlSet = new HashSet<String>();
                        List<Map<String, Object>> requestMethodList =
                                (List<Map<String, Object>>) power.get("requestMethodList");
                        for (Map<String, Object> requestMethod : requestMethodList) {
                            List<RequestMethodB> requestMethodBList =
                                    (List<RequestMethodB>) requestMethod.get("requestMethodBList");
                            for (RequestMethodB requestMethodB : requestMethodBList) {
                                methodSet.add(requestMethodB.getRequestMethod());
                            }
                        }
                        List<Map<String, Object>> requestUrlList =
                                (List<Map<String, Object>>) power.get("requestUrlList");
                        for (Map<String, Object> requestUrl : requestUrlList) {
                            List<RequestUrlB> requestUrlBList = (List<RequestUrlB>) requestUrl.get("requestUrlBList");
                            for (RequestUrlB requestUrlB : requestUrlBList) {
                                urlSet.add(requestUrlB.getRequestUrl());
                            }
                        }
                        boolean containMethod = false;
                        boolean containUrl = false;
                        Iterator<Integer> methodIterator = methodSet.iterator();
                        while (methodIterator.hasNext()) {
                            if (methodIterator.next() == 1 && "GET".equals(method)) {
                                containMethod = true;
                                break;
                            }
                            if (methodIterator.next() == 2 && "POST".equals(method)) {
                                containMethod = true;
                                break;
                            }
                        }
                        Iterator<String> urlIterator = urlSet.iterator();
                        while (urlIterator.hasNext()) {
                            if (antPathMatcher.match(urlIterator.next(), url)) {
                                containUrl = true;
                                break;
                            }
                        }
                        if (containMethod && containUrl) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

}
